<script setup lang="ts">
import { BaseApi } from "@/apis/base.api";
import { UtilTool } from "@webxue/common";
import { onMounted, reactive } from "vue";
import { useWebxRouteTabs } from "@webxue/vue3-antdv-ui";
import { Empty } from "ant-design-vue";
import useForm from "@/hooks/useForm";
import useCusRouter from "@/hooks/useCusRouter";
import EventEmitTool from "@/utils/tools/event-emit.tool";

// 获取路由属性
const { router, routeQuery } = useCusRouter({
  queryKeys: [
    // 角色id
    "roleId",
    // 是否只读
    "readonly"
  ]
});
// 页签
const { addParentTab } = useWebxRouteTabs({ router });
// 获取详情hook
const { detailInfo, formRef, formState, onValidateFields, getFormRules } = useForm({
  // 获取表单数据
  formState: {} as Record<string, any>,
  // 获取详情数据
  async onInit() {
    // 数据初始化
    formState.value.status = 1;

    if (!routeQuery.value.roleId) return false;
    const response = await BaseApi.role.find({ id: routeQuery.value.roleId });
    // 回显角色信息
    formState.value = UtilTool.lodash.cloneDeep(response.data);
    // 回显关联权限
    permissionData.rolePermissionIds = formState.value.permissionIds?.split(",") || [];
    // 回显关联菜单
    menuGroupData.checkMenuGroupMenuIds = formState.value.menuList.reduce((acc, menu) => {
      if(!acc[menu.menuGroupId]) {
        acc[menu.menuGroupId] = [];
      }
      acc[menu.menuGroupId].push(menu.id);
      return acc;
    }, {});
    return Promise.resolve(response);
  },
  // 表单校验成功回调
  async onValidateSuccess(values) {
    // 响应结果
    let response: Partial<ResponseData> = {};
    // 请求参数
    const requestBody: Record<string, any> = {
      name: values.name,
      code: values.code,
      description: values.description,
    };
    // 绑定关联角色
    if (permissionData.rolePermissionIds.length) {
      requestBody.permissionIds = permissionData.rolePermissionIds.join(",");
    }
    // 绑定关联菜单
    if(Object.values(menuGroupData.checkMenuGroupMenuIds).flat(Infinity).length) {
      requestBody.roleMenus = Object.entries(menuGroupData.checkMenuGroupMenuIds).reduce((acc, [menuGroupId, menuIdArr]) => {
        return acc.concat(menuIdArr.map(menuId => ({ menuId, menuGroupId })));
      },[]);
    }
    if (routeQuery.value.roleId) {
      // 编辑
      response = await BaseApi.role.update({
        ...requestBody,
        id: routeQuery.value.roleId
      });
    } else {
      // 新增
      response = await BaseApi.role.save({
        ...requestBody
      });
    }
    if (response.success) {
      addParentTab();
    }
  }
});
// 权限管理
const permissionData = reactive({
  permissionList: [] as any[],
  rolePermissionIds: [] as string[],
  async set() {
    const response = await BaseApi.permission.list({ queryType: "all" });
    permissionData.permissionList = response.data;
  }
});
// 菜单组管理
const menuGroupData = reactive({
  // 菜单组列表
  menuGroupList: [] as any[],
  // 勾选的菜单组菜单
  checkMenuGroupMenuIds:{} as Record<string, string[]>,
  // 设置菜单组列表
  async setMenuGroupList() {
    const response = await BaseApi.menuGroup.list({ queryType: "all" });
    menuGroupData.menuGroupList = response.data.map(mg => ({
      ...mg,
      children: UtilTool.makeTree(mg.menuList, ["id", "parentId"])
    }));
  }
});

// form保存回调
EventEmitTool.on("FORM:SAVE", () => {
  // 开始校验
  onValidateFields();
});

onMounted(async () => {
  // 设置权限
  await permissionData.set();
  // 设置菜单组
  await menuGroupData.setMenuGroupList();
});
</script>

<template>
  <div>
    <WebxForm ref="formRef" :model="formState" :readonly="!!routeQuery.readonly">
      <div class="flex flex-col gap-2">
        <WebxCard :titleProps="{ title: '角色维护' }">
          <ARow class="px-2 pb-4" :gutter="[0, 10]">
            <ACol :span="8">
              <WebxFormItem
                label="角色名称"
                name="name"
                :rules="[{ required: true, message: '请输入角色名称' }]"
              >
                <AInput v-model:value="formState.name" placeholder="请输入角色名称" />
                <template #readonly>{{ formState.name }}</template>
              </WebxFormItem>
            </ACol>
            <ACol :span="8">
              <WebxFormItem
                label="角色编码"
                name="code"
                :rules="[{ required: true, message: '请输入角色编码' }]"
              >
                <AInput
                  v-model:value="formState.code"
                  placeholder="请输入角色编码"
                  :disabled="!!routeQuery.roleId"
                />
                <template #readonly>{{ formState.code }}</template>
              </WebxFormItem>
            </ACol>
            <ACol :span="24">
              <WebxFormItem label="描述" name="description">
                <ATextarea
                  v-model:value="formState.description"
                  placeholder="请输入描述"
                  :autoSize="{ minRows: 4, maxRows: 4 }"
                />
                <template #readonly>{{ formState.description }}</template>
              </WebxFormItem>
            </ACol>
          </ARow>
        </WebxCard>
        <WebxCard :titleProps="{ title: '权限分配' }">
          <ACheckboxGroup
            v-model:value="permissionData.rolePermissionIds"
            :disabled="!!routeQuery.readonly"
          >
            <ACheckbox
              v-for="permission in permissionData.permissionList"
              :key="permission.id"
              :value="permission.id"
            >
              {{ permission.permissionName }}
            </ACheckbox>
          </ACheckboxGroup>
        </WebxCard>
        <WebxCard :titleProps="{ title: '菜单分配' }">
          <WebxGridList
            :dataSource="menuGroupData.menuGroupList"
            :colCount="3"
            :showFooter="() => false"
          >
            <template #title="{ name }">{{ name }}</template>
            <template #content="data">
              <ATree v-if="data.children.length"
                checkable
                defaultExpandAll
                :selectable="false"
                :key="data.children.length"
                v-model:checkedKeys="menuGroupData.checkMenuGroupMenuIds[data.id]"
                :treeData="data.children"
                :fieldNames="{ title:'name', key:'id', children: 'children' }"
              />
              <AEmpty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
            </template>
          </WebxGridList>
        </WebxCard>
      </div>
    </WebxForm>
  </div>
</template>

<style scoped lang="less">
.ant-form-item {
  margin-bottom: 0;
  :deep(.ant-form-item-label) {
    width: 120px;
  }
}
</style>
